function expand(cells, d = 10) {
    out = []
    var top = Array.from({ length: d }, (_, i) => Array.from({ length: 2 * d + cells[0].length }, (_, j) => 0));
    var middle = cells.map(v => {
        var temp = Array.from({ length: d }, (_, i) => 0);
        temp = temp.concat(v);
        temp = temp.concat(Array.from({ length: d }, (_, i) => 0));
        return temp;
    });
    return out.concat(top).concat(middle).concat(top)
}

function cut(cells) {
    while (cells[0].every(v => v === 0)) cells.shift();
    while (cells[cells.length - 1].every(v => v === 0)) cells.pop();
    while (cells.map(v => v[0]).every(v => v === 0)) cells = cells.map(v => v.slice(1))
    while (cells.map(v => v[v.length - 1]).every(v => v === 0)) cells = cells.map(v => v.slice(0, -1))
    return cells
}

function get_neighbour_lives(i, j, cells) {
    var diffs = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
    var lives = 0;
    diffs.forEach(([dx, dy]) => {
        var [row, col] = [i + dx, j + dy];
        if (row > -1 && row < cells.length && col > -1 && col < cells[0].length && cells[row][col]) lives++;
    });
    return lives;
}

function getGeneration(input_cells, generations) {
    var cells = expand(input_cells.map(v => [].concat(v)));
    for (var t = 0; t < generations; t++) {
        var copy = cells.map(v => [].concat(v));
        for (var i = 0; i < copy.length; i++) {
            for (var j = 0; j < copy[0].length; j++) {
                var lives = get_neighbour_lives(i, j, cells);
                if (copy[i][j]) {
                    if (lives < 2 || lives > 3) copy[i][j] = 0;
                } else {
                    if (lives === 3) copy[i][j] = 1;
                }
            }
        }
        cells = copy.map(v => [].concat(v));
    }
    return cut(cells);
}
console.log(getGeneration([
    [1, 0, 0],
    [0, 1, 1],
    [1, 1, 0]
], 2))